System.AccessViolationException error when accessing COM DLL written in Visual FoxPro - c#

I have a C# WinForms .NET 3.5 application that I need to call a COM DLL written in Visual FoxPro 7. I have added the COM object to the C# project fine, and can
view the objects and its members in the object browser fine.
However when I attempt to call any methods or access any properties from the COM object I get the following exception thrown :
System.AccessViolationException was unhandled
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Source=Interop.emscosting
StackTrace:
at emscosting.ComBaseClass.ShellExecute(String tcItem, String tcAction)
...
Below is some example C# code I am using :
emscosting.ComBaseClass com = new emscosting.ComBaseClass();
com.ShellExecute(file, "TRUE"); <--- The exception is thrown here
Also when I try and access any of the public properties of the COM object in the debugger watch window I get the following appear in the Value column :
'com.DatabaseUserName' threw an exception of type 'System.AccessViolationException'
I am already using this COM object without any issues from other VFP applications, Office applications, and in Javascript/Classic ASP.
Can someone help me resolve this issue please ?
I do have the original VFP source code for the COM still and below is a snippet of the code where I am declaring the public properties, however I am trying to
avoid rewriting the COM DLL if possible!
#If BUILD_AS_COM_OBJECT
Define Class emsCosting As Combase OlePublic
#Else
Define Class emsCosting As Combase
#Endif
CostingsPath = COSTINGS_PATH
Dimension CostingsPath_COMATTRIB[5]
CostingsPath_COMATTRIB[1] = COMATTRIB_NONE
CostingsPath_COMATTRIB[2] = "Contains the path of where the costings get saved" && HelpString
CostingsPath_COMATTRIB[3] = "CostingsPath" && Capitalisation
CostingsPath_COMATTRIB[4] = "String" && Property Type
CostingsPath_COMATTRIB[5] = 0 && Number of parameters
CostingsMaster = COSTINGS_MASTER
Dimension CostingsMaster_COMATTRIB[5]
CostingsMaster_COMATTRIB[1] = COMATTRIB_NONE
CostingsMaster_COMATTRIB[2] = "Contains the filename of the costings master (usually costings.xls)" && HelpString
CostingsMaster_COMATTRIB[3] = "CostingsMaster" && Capitalisation
CostingsMaster_COMATTRIB[4] = "String" && Property Type
CostingsMaster_COMATTRIB[5] = 0 && Number of parameters
Function SetCostingsPath(tcPath As String) As VOID HelpString "This is a test function"
CostingsPath = tcPath
EndFunc
Function TestFunctionNoParam() AS String HelpString "This is a helpstring"
Return "\\TEST\ContractReviewCostings\"
EndFunc
......
NOTE: Both the two test functions defined above fail with the exception System.AccessViolationException

You have to compile your .Net Application for x86, if you have a x64 system.
When you compile it with "Any CPU" or "x64", you can not access the x32 FoxPro-DLL.

Related

Issues with using Managed WiFi (NativeWiFi API)

I am trying to create and connect to a WLAN profile using Native WiFi (https://managedwifi.codeplex.com/). I am able to view all the Network BSS List and their parameters. However, when I am trying to create/overwrite a WLAN profile, I get the below mentioned error message (Error#1):
An unhandled exception of type 'System.ComponentModel.Win32Exception' occurred in ManagedWifi.dll.
Additional information: The network connection profile is corrupted
However, when I created a profile normally from "Network and Sharing Center" of the Windows 7 control panel and then tried to connect using the ManagedWiFi, I get another error message(Error#2):
An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll
Additional information: Type 'NativeWifi.Wlan+WlanReasonCode' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.
I noticed that this error occurs even if I try to connect/disconnect to a WLAN profile from the "Network and Sharing Center", with the windows application running in the background.
Here is the sample code that I am using:
Dim profileName As String = GlobalVariables.ssidname ' Provides the selected SSID name from the Network BSS List
Dim hexval As String = StringToHex(GlobalVariables.ssidname) ' Function to get the hexadecimal value for a provided string
Dim key As String = TextBox1.Text ' Security key from the textbook provided
Dim profileXml As String = String.Format("<?xml version=""1.0""?><WLANProfile xmlns=""http://www.microsoft.com/networking/WLAN/profile/v1""><name>{0}</name><SSIDConfig><SSID><hex>{1}</hex><name>{0}</name></SSID></SSIDConfig><connectionType>ESS</connectionType><MSM><security><authEncryption><authentication>open</authentication><encryption>WEP</encryption><useOneX>false</useOneX></authEncryption><sharedKey><keyType>networkKey</keyType><protected>false</protected><keyMaterial>{2}</keyMaterial></sharedKey><keyIndex>0</keyIndex></security></MSM></WLANProfile>", 'GlobalVariables.ssidname, hexval, TextBox1.Text)
wlanIface.SetProfile(Wlan.WlanProfileFlags.AllUser, profileXml, True) 'Error#1 occurs here
wlanIface.Connect(Wlan.WlanConnectionMode.Profile, Wlan.Dot11BssType.Any, profileName) 'Error#2 occurs here
From the forum "Type Native Wifi.Wlan + WlanReasonCode cannot be marshaled error", the issue (Error#2) seems to be within the WlanAPI.cs, where there is a line of code that checks for the size of the return code. This is the line:
int expectedSize = Marshal.SizeOf(typeof(Wlan.WlanReasonCode));
if (notifyData.dataSize >= expectedSize)
{
Wlan.WlanReasonCode reasonCode = (Wlan.WlanReasonCode)Marshal.ReadInt32(notifyData.dataPtr);
if (wlanIface != null)
wlanIface.OnWlanReason(notifyData, reasonCode);
}
Changing the above code to the below seems to fix the issue.
//int expectedSize = Marshal.SizeOf(typeof(Wlan.WlanReasonCode));
if (notifyData.dataSize >= 0)
{
Wlan.WlanReasonCode reasonCode = (Wlan.WlanReasonCode)Marshal.ReadInt32(notifyData.dataPtr);
if (wlanIface != null)
wlanIface.OnWlanReason(notifyData, reasonCode);
}
However, I am not sure on how to add this fix to my solution. I installed the ManagedWiFi from the NuGet Package Manager. Hence, not sure how to change the WlanApi.cs file. Any help regarding the above mentioned two issues are much appreciated.
The issue (Error#1) is now resolved. The profilexml file format was different for me. Here is the profilexml after I changed it.
Dim profileXml As String = String.Format("<?xml version=""1.0""?><WLANProfile xmlns=""http://www.microsoft.com/networking/WLAN/profile/v1""><name>{0}</name><SSIDConfig><SSID><hex>{1}</hex><name>{0}</name></SSID></SSIDConfig><connectionType>ESS</connectionType><connectionMode>auto</connectionMode><MSM><security><authEncryption><authentication>WPA2PSK</authentication><encryption>AES</encryption><useOneX>false</useOneX></authEncryption><sharedKey><keyType>passPhrase</keyType><protected>false</protected><keyMaterial>{2}</keyMaterial></sharedKey></security></MSM></WLANProfile>", GlobalVariables.ssidname, hexval, TextBox1.Text)
Also the second issue (Error#2) was resolved when I uninstalled ManagedWiFi package from my solution and added the whole ManagedWiFi project to the solution. Then I made the change in WlanApi.cs as mentioned in SimpleWiFi Or Type Native Wifi.Wlan + WlanReasonCode cannot be marshaled error.
I had a simpler task (read the SSID of the connected network), which was throwing the same error.
I solved it by switching to using SimpleWiFi entirely and ignore the ManagedWifi package.
Glancing at the source code, it looks like SW is a fixed reimplementation of some of the functionality in MW.

Executing python script with zmq from C# using IronPython not working

I'm using ZeroMQ for inter-process communication between C# managed application and python script. When calling script from C#, using IronPython I get following error :
An unhandled exception of type
IronPython.Runtime.Exceptions.ImportException occurred in
Microsoft.Dynamic.dll
Additional information: cannot import constants from
zmq.backend.cython
Python code (test.py file):
import sys, zmq, time
def execute(input):
context = zmq.Context()
publisher = context.socket(zmq.PUB)
publisher.bind("tcp://*:18800")
time.sleep(1)
publisher.send(input) #just echo input parameter
And this is how I execute .py code from my C# app :
static void Main(string[] args)
{
var options = new Dictionary<string, object>();
options["Frames"] = true;
options["FullFrames"] = true;
ScriptEngine _engine = Python.CreateEngine(options);
ScriptRuntime _runtime = _engine.Runtime;
ICollection<string> _searchPaths = _engine.GetSearchPaths();
_searchPaths.Add(#"C:\Python27\");
_searchPaths.Add(#"C:\Python27\Lib\");
_searchPaths.Add(#"C:\Python27\Scripts\");
_searchPaths.Add(#"C:\Python27\libs\");
_searchPaths.Add(#"C:\Python27\DLLs\");
_searchPaths.Add(#"C:\Python27\include\");
_searchPaths.Add(#"C:\Python27\lib\site-packages");
_engine.SetSearchPaths(_searchPaths);
dynamic wrapperObj = _runtime.UseFile("test.py");
wrapperObj.execute("test");
}
Note that some code is omitted for brevity, and not actually relevant for this scenario. When manually invoking .py script through the command line, everything works fine, I'm able to pass data around and my C# app is receiving messages.
Anyone knows what is this error and how can be solved?
EDIT : While I was desperate and almost gave up, I tried to write quick named-pipes support, and guess what - similar error:
An unhandled exception of type IronPython.Runtime.Exceptions.ImportException occurred in
Microsoft.Dynamic.dll
Additional information: No module named win32file
This time, my test.py looks like this:
import win32file
def execute(input):
handle = win32file.CreateFile(r"\\.\pipe\test_pipe",
win32file.GENERIC_WRITE,
0, None,
win32file.OPEN_EXISTING,
0, None)
if handle:
win32file.WriteFile(self.handle, input, None)
win32file.FlushFileBuffers(self.handle)
win32file.SetFilePointer(self.handle, 0, win32file.FILE_BEGIN)
I'm not really sure if I have more options for this kind of interoperability, but I'm starting to think that IronPython can just cover basic usage scenarios (when calling pure python code from C#), not to mention matplotlib, numpy or astropy that I will certanly need later on.
Thanks in advance!
Regards,
Civa

NLua and generic methods

I am trying to run following lua code with DoFile() in NLua :
import('TestStack.White');
src=luanet.import_type('TestStack.White.UIItems.Finders.SearchCriteria')
application=Application.Launch('C:\\windows\\system32\\calc.exe')
win = application:GetWindow("Calculator");
win:WaitWhileBusy();
btnOne=win:Get(src.ByText("1")) <<---Exception here
btnOne:Click();
win:WaitWhileBusy();
I get following exception while executing this :
{Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.}
Equaivalent .net code which works fine is :
Application application = Application.Launch(#"C:\windows\system32\calc.exe");
Window window = application.GetWindow("Calculator");
window.WaitWhileBusy();
var btnOne = window.Get(SearchCriteria.ByText("1"));
btnOne.Click();
window.WaitWhileBusy();
Please help getting rid of this exception.
Additionally, I would also like to know "
Is there a way to load a dll using lua , not already loaded in my .net application?"

Use C++ Component Object Model in C#

I am trying to build a COM Library in C++, using a C# project for testing. Some methods need to return strings to the caller. On calling these methods from C# I get this: "Access violation reading at location ..."
This is the C++ code from my testproject (apart from all the stuff generated by VS 2010 ATL)
//COMTest.idl
[id(1)] HRESULT Test([out,retval] BSTR* ret);
//Program2.h
STDMETHOD(Test)(BSTR* ret);
//Program2.cpp
STDMETHODIMP CProgram2::Test(BSTR* ret)
{
BSTR tmp = (BSTR)CoTaskMemAlloc(sizeof(wchar_t) * 2);
tmp[0] = L'H';
tmp[1] = L'\0';
*ret = (BSTR)tmp;
return S_OK;
}
In C# I just referenced the DLL from the COM-Tab, turned "Embed Interop Types" off, because it caused errors, and ran this:
static void Main(string[] args)
{
COMTestLib.Program2Class instance = new COMTestLib.Program2Class();
string tmp = instance.Test(); //Where the error occurs
Console.WriteLine(tmp); //This is not reached
Console.Read();
}
The error occurs after leaving the Test-Method. I debugged the C++ code from within my C# project and the values are placed in the correct locations. I do not get the error if I try to return 0 (gives null in C#), even if I still allocate memory like in the example.
I can not make sense of the address, which the access violation complains about. It is neither the address I am allocating nor any other address used in the method. What also seems weird to me is that the CoTaskMemAlloc-Function always returns addresses with the first byte set to zero (0x00XXXXXX), but that might just be a COM thing.
I ran out of ideas and I cant find much information on this (except for basic COM tutorials) anywhere. Can anyone help?
BSTRs require extra memory (to keep track of the string len) so must use SysAllocString() function to allocate BSTRs (or use one of the "smart" BSTR classes).
So your original code should read like:
//Program2.cpp
STDMETHODIMP CProgram2::Test(BSTR* ret)
{
*ret = SysAllocString(L"H");
return S_OK;
}
A good reading about BSTRs: http://blogs.msdn.com/b/ericlippert/archive/2003/09/12/52976.aspx
Check that your COM project and test project are both STA. Check the bitness too. What if you replace BSTR by LPSTR ?

Vista TaskDialog Wrapper: Unable to find an entry point named 'TaskDialogIndirect' in DLL 'ComCtl32'

I'm try to use Vista TaskDialog Wrapper and Emulator and I'm getting the following exception:
"Unable to find an entry point named 'TaskDialogIndirect' in DLL 'ComCtl32'."
...in a simple Console application:
class Program
{
[STAThread]
static void Main(string[] args)
{
System.Threading.Thread.CurrentThread.CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
PSTaskDialog.cTaskDialog.MessageBox(
"MessageBox Title",
"The main instruction text for the message box is shown here.",
"The content text for the message box is shown here and the text willautomatically wrap as needed.",
PSTaskDialog.eTaskDialogButtons.YesNo,
PSTaskDialog.eSysIcons.Information
);
}
}
What am I doing wrong?
UPDATE:
Actually, I'm working on an Excel plugin using excel-dna. How can I control what dll Excel loads?
http://exceldna.codeplex.com/discussions/286990#post728888
I haven't been at Office programming in a while, but my guess is that Excel loads both versions of comctl32, so you may need to use the Activation Context API to direct your code to the version that includes TaskDialog. Some ideas for fixing the problem (not solutions as such):
For test purposes, make a temporary enumeration of all modules in the active process - just to check if 6.10 is actually loaded (see below for a simple example of such an enumeration, albeit with a different intent).
Use the Activation Context API to get to the right version. Example of use from C# (for enabling themes by way of comctl32 6.0) here.
Alternatively (I never actually got this to work reliably in a WPF application I worked on), make a dialog abstraction class, which falls back to MessageDlg depending on the version available to you. There may be better ways of doing the check, but...:
FileVersionInfo version = ProcessUtils.GetLoadedModuleVersion("comctl32.dll");
if (version != null && version.FileMajorPart >= 6 && version.FileMinorPart >= 1)
{
// We can use TaskDialog...
}
else
{
// Use old style MessageBox
}
The enumeration of modules:
internal static FileVersionInfo GetLoadedModuleVersion(string name)
{
Process process = Process.GetCurrentProcess();
foreach (ProcessModule module in process.Modules)
{
if (module.ModuleName.ToLower() == name)
{
return module.FileVersionInfo;
}
return null;
}
}
In addition to what all the others are saying: This error will disappear if you set the ForceEmulationMode on PSTaskDialog to true.

Categories

Resources