|
Hey everybody!
Lets assume the following function signature:
void do_something(byte* input, byte* output);
The function is taking the input, doing something with it and places the result in output.
The function uses "new byte(X)" command, and returns this new byte* (in other words, the caller must delete the variable when done).
Now, We're putting this function in COM, and calling it from C#.
So, in C++ we're using "new", and it returns to C#.
Does c# take care of the assigned memory in this scenario ???
Thanks a lot in advance!!!
|
|
|
|
|
As the memory is not allocated from the managed memory, it's not garbage collected. The calling code will have to delete the memory.
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
|
Green Fuze wrote: Does c# take care of the assigned memory in this scenario ???
Nope. See, for instance, here [^].
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
|
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Whenever you allocate memory in a COM component that you intend to return to the caller, you should use COM's memory allocator, which you can obtain by calling CoGetMalloc . There's a straightforward wrapper for allocation called CoTaskMemAlloc , which has the counterparts CoTaskMemRealloc for increasing the block's size, and CoTaskMemFree for freeing memory allocated this way.
The COM runtime will have to manage memory for you any time it passes any kind of boundary, so you should always do this even with C++ clients and servers. It's a good idea to do it properly
In your IDL, you will need to provide attributes to tell the marshalling layer what pointers actually mean. Do these point to one byte, or to an array of bytes? If it's an array, you'll need to provide information about whether it's null terminated ([string] ) or what the size of the array is ([size_is] ).
If you mean one byte, the runtime will be expecting the caller to pass a pointer to a location where the byte should be stored, and the called function should write directly to that address without allocating.
If you really mean passing in one byte and returning one byte, I'd write it:
void do_something(byte input, [out] byte* output); [out] just tells MIDL that the value is an output and doesn't need to be marshalled on the 'in' direction (this means the function will receive junk data). I've changed the first parameter to a single byte passed by value.
In addition you should really make the return type HRESULT . This is the only way to signal faults; if a failure HRESULT is returned, the .NET marshalling layer will throw the corresponding exception.
DoEvents: Generating unexpected recursion since 1991
|
|
|
|
|
Thanks a lot!
That really helped!
|
|
|
|
|
Since this morning VStudio 2008 refuses to work.
I wanted to open VStudio by double-clicking a sln-file. VStudio opened for approximately 1 seconds and than it closed again (automatically)
If I open VStdio directly by starting from start-menu (without double-clicking a sln-file) than it opens. BUT: When I try to load a sln-file via menu (file-open solution) than I get the following message:
"Microsoft Visual Studio has encountered a problem and needs to close"
I have no idea!
I also observed that VStudio blocked some actions for a very long time the last days.
Does anybody have some idea?
|
|
|
|
|
Hi,
I'd try manually cleaning project/solution by deleting all the bin and obj folders.
If that fails to work and if you're more concerned with getting back to work than figuring out what caused it one solution is to create an new solution and add everything (source files, .resx files etc) from the broken solution to that one.
/Fredrik
|
|
|
|
|
It sounds like some files have become corrupted. Check if there is a Repair option in the installation.
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
I perfromed a repair - it dit not help.
((
|
|
|
|
|
I have a created a window which has one show button which searches some information from my LAN pc's, but what i want is to display a progress window , having the image "please wait" for this i have created a separate window and called the show method , Now when this progress window is opened , user should not switch to the parent window, how can i do that ?.
Regards
|
|
|
|
|
Show the progress window as modal but make sure you are doing it from a separate thread, your main thread will be blocked else.
|
|
|
|
|
|
Application.DoEvents ??
it is helpfully (sometimes)
|
|
|
|
|
It's trivial. You run the searching in a separate thread and show modal progress window from the main thread. Something like
ThreadPool.QueueUserWorkItem(DoSearching,AnyObject);
progress.ShowDialog() "DoSearching " method should be able to update and close the progress. Make sure you use Invoke/BeginInvoke when accessing progress window from your DoSearching method.
|
|
|
|
|
When i search about BeginInvoke /Invoke every where written that u should avoid them because it causes deadlocks and also slow. Any better idea
|
|
|
|
|
I never experienced any problem with that. CP has an excellent article on Invoke/BeginInvoke here[^]. It's worth reading.
|
|
|
|
|
Ok i have created a function progress() and uses MethodInvoker and called BeginInvoke(), Now in progress() function i called the progress.showdialog() after begininvoke i called method of extracting details from the network , when this function returns i closes the form progress.close() but gives error why? how can i close my show dialog form.
|
|
|
|
|
|
using System;
using Microsoft.Win32;
using System.Management;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Collections;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
using System.Windows;
using System.Configuration;
using System.Threading;
namespace LogApplication
{
public partial class Event_frm : Form
{
ArrayList entries = new ArrayList();
DataGridBoolColumn col = new DataGridBoolColumn();
string selectedPath;
Progress progress = new Progress();// check here it is a form
public Event_frm()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
btnDownload.Enabled = false;
chbSelect.Enabled = false;
string strHostName = Dns.GetHostName();
}
private void button1_Click(object sender, EventArgs e)
{
ArrayList machine_names = new ArrayList();
machine_names.Clear();
for (int i = 0; i < gvMachine.RowCount; i++)
{
if (gvMachine.Rows[i].Cells[0].Value != null)
{
machine_names.Add(gvMachine.Rows[i].Cells[1].Value);
}
}
if (machine_names.Count <= 0)
{
MessageBox.Show("Please select atleast one machine name");
}
else
{
Credentials credentials = new Credentials();
credentials.username = "Administrator";
credentials.password = "1A2B3c456789$";
if (dgFolderBrowse.ShowDialog() == DialogResult.OK)
{
selectedPath = dgFolderBrowse.SelectedPath;
}
else
{
return;
}
if (rbtSoft_Inven_Info.Checked)
{
credentials.managementPath = @"\root\cimv2";
LogApplication.RegistryScan registryScan = new LogApplication.RegistryScan();
Hashtable registryEntries = registryScan.getRegistryEntries(machine_names, credentials);
ArrayList pass=(ArrayList)registryEntries["pass"];
ArrayList fail=(ArrayList)registryEntries["fail"];
FileWriter writer = new FileWriter();
int created = writer.write(pass, fail, selectedPath);
if (created > 0)
{
MessageBox.Show("Data Written");
}
}
else
{
credentials.managementPath = @"\root\cimv2";
if (ddEventType.SelectedIndex == -1)
{
errorProvider.DataSource = ddEventType;
errorProvider.SetError(ddEventType, "Please select valid event type");
ddEventType.Focus();
}
else
{
DateTime dateFrom;
DateTime dateEnd;
try
{
dateFrom = DateTime.Parse(string.Format("{0 }", dtFrm.Value));
}
catch (Exception ex)
{
MessageBox.Show("Invalid Start Date ");
dtFrm.Focus();
return;
}
try
{
dateEnd = DateTime.Parse(string.Format("{0 }", dtEnd.Value.AddDays(1)));
}
catch (Exception ex)
{
MessageBox.Show("Invalid End Date");
dtEnd.Focus();
return;
}
if (dateFrom <= dateEnd)
{
Hashtable logEntries = new EventLog().getLogEntries(machine_names,ddEventType.Text,credentials,dateFrom,dateEnd);
ArrayList pass = (ArrayList)logEntries["pass"];
ArrayList fail = (ArrayList)logEntries["fail"];
FileWriter writer = new FileWriter();
int created = writer.write(pass, fail, selectedPath);
if (created > 0)
{
MessageBox.Show("Data Written");
}
}
else
{
errorProvider.SetError(dtEnd, "End date should be less than or equal to Start date");
}
}
}
}
}
ArrayList generateMachineNames()
{
ProcessStartInfo pinfo = new ProcessStartInfo("net", "view");
pinfo.RedirectStandardOutput = true;
pinfo.UseShellExecute = false;
pinfo.CreateNoWindow = true;
using (Process p = new Process())
{
try
{
p.StartInfo = pinfo;
p.Start();
ArrayList machine_names = new ArrayList();
while (!p.StandardOutput.EndOfStream)
{
string read = p.StandardOutput.ReadLine().Trim();
if (read.StartsWith("\\\\"))
{
string[] machines = read.Split(' ');
machine_names.Add(machines[0].Substring(2).Trim());
}
}
return machine_names;
}
catch (IOException IOException)
{
MessageBox.Show("Error occurred in generating IP list, "+IOException.Message);
return null;
}
catch (Exception ex)
{
MessageBox.Show("Error occurred : " + ex.Message);
return null;
}
}
}
void loadMachines(ArrayList machineList)
{
int count = 0;
foreach (string machine in machineList)
{
gvMachine.Rows.Add();
gvMachine.Rows[count].Cells[1].Value = machine;
count++;
}
}
void loadMachines(string machine)
{
gvMachine.Rows.Add();
gvMachine.Rows[0].Cells[1].Value = machine;
}
private void rbtSoft_Inven_Info_CheckedChanged(object sender, EventArgs e)
{
ddEventType.Enabled = false;
dtFrm.Enabled = false;
dtEnd.Enabled = false;
}
private void rbtEvent_log_history_CheckedChanged(object sender, EventArgs e)
{
ddEventType.Enabled = true;
dtFrm.Enabled = true;
dtEnd.Enabled = true;
}
private void btnSearch_Click(object sender, EventArgs e)
{
if (rbtRemote.Checked == false && rbtLocal.Checked == false)
{
errorProvider.SetError(btnSearch, "Please, select one option");
}
else
{
if (rbtRemote.Checked)
{
// CHECK HERE ALSO
MethodInvoker invoker = new MethodInvoker(showProgress); /check here
invoker.BeginInvoke(null,null); //here tooooo
ArrayList machineList = generateMachineNames();
if (machineList == null || machineList.Count == 0)
{
MessageBox.Show("No machines are available, please check your network or try again");
btnDownload.Enabled = false;
if (gvMachine.Rows.Count > 0)
{
gvMachine.Rows.Clear();
}
progress.Close();
progress.Dispose();
}
else
{
loadMachines(machineList);
btnDownload.Enabled = true;
chbSelect.Enabled = true;
progress.Close();// here i got error
progress.Dispose();
}
}
else
{
try
{
string machine = Dns.GetHostName();
loadMachines(machine);
btnDownload.Enabled = true;
}
catch (SocketException SocketException)
{
MessageBox.Show("Error occurred in getting local machine name, " + SocketException.Message);
}
catch (Exception ex)
{
MessageBox.Show("Error occurred , " + ex.Message);
}
}
}
}
private void chbSelect_CheckedChanged(object sender, EventArgs e)
{
if (chbSelect.Checked)
{
for (int i = 0; i < gvMachine.RowCount; i++)
{
gvMachine.Rows[i].Cells[0].Value = true;
}
}
else
{
for (int i = 0; i < gvMachine.RowCount; i++)
{
gvMachine.Rows[i].Cells[0].Value = false;
}
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
try
{
Environment.Exit(0);
}
catch (System.Security.SecurityException SecurityException)
{
MessageBox.Show(SecurityException.Message);
}
}
void showProgress()//this is the method
{
progress.ShowDialog();
}
}
}
|
|
|
|
|
You are doing just opposite to what I said. I reiterate, do long running process on the method which you are invoking using MethodInvoker . Show progress dialog in the main thread. When the long running process finishes, end the progress window. You will get cross thread access error when you try to close the progress, so use Invoke/BeginInvoke to close the progress window safely.
|
|
|
|
|
If i put in the main thread then the execution hangs on showdialog() call
|
|
|
|
|
Hi,
I'd like to invoke a couple of methods retrieved from multiple,
dynamically loaded Assemblies (I have the MethodInfo objects)
asynchronously and wait for all methods to finish processing before I
continue. The method signature is:
public void ProcessJob(JobInfo job);
Can this be done? If so, how? Thanks in advance.
Kind regards
/matthias
I love deadlines. I like the whooshing sound they make as they fly by. [Douglas Adams]
|
|
|
|