473,545 Members | 2,047 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Help calling function from DLL and processing returned value (Can not marshal return value)

Hi again,
I'm trying to call functions from a proprietary DLL but it's turned out to
be more difficult than I thought.

I have this W32.DLL which was written in C by USPS. They don't provide the
code so I only have the documentation.
I'm trying to call a function called z4date that, according to the docs,
returns the date as "an 8-byte character string in the "YYYYMMDD" format".
When I run it with this code I've written , I get "Can not marshal return
value".

My real concern is that, if I'm having trouble with these functions that
return simple data types, how am I going to interact with functions that
return user-defined data types?

This is what I've written in the class so far:

....
using System.Runtime. InteropServices ;
namespace ZM7
{
/// <summary>
/// Summary description for AMS.
/// </summary>
public class AMS
{
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")]
public static extern int z4open(); //another function from the dll
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")] /* Do I need to use
DllImport for every fiunction I'm using? */
public static extern byte[] z4date();
....

public byte[] getDate()
{
Byte[] myDate;
myDate = new Byte[8];
myDate = z4date(); //function call where I receive error "Can not
marshal return value"
return myDate();
}

Any help is appreciated.
Nov 15 '05 #1
9 2806
Angel,

You will not be able to do this. The reason that it doesn't work with
your definitions is because the pointer that is being returned by the
function is of an indeterminate nature. True, the documentation states that
it returns eight bytes, but there is nothing in the code that indicates that
is the case.

To get around this, you should declare your return type as an IntPtr,
and then pass that to the static PtrToStringAnsi method on the Marshal
class.

The only thing to be considerate of is the fact that the function
allocated memory and returned it. To prevent a leak, you will have to
dispose of the memory pointed to by the IntPtr. How you do this is
dependent on how the DLL allocates it, and will require another call through
P/Invoke.

Also, you do have to use the attribute for every declaration.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Angel" <none> wrote in message
news:u5******** ******@tk2msftn gp13.phx.gbl...
Hi again,
I'm trying to call functions from a proprietary DLL but it's turned out to
be more difficult than I thought.

I have this W32.DLL which was written in C by USPS. They don't provide the
code so I only have the documentation.
I'm trying to call a function called z4date that, according to the docs,
returns the date as "an 8-byte character string in the "YYYYMMDD" format".
When I run it with this code I've written , I get "Can not marshal return
value".

My real concern is that, if I'm having trouble with these functions that
return simple data types, how am I going to interact with functions that
return user-defined data types?

This is what I've written in the class so far:

...
using System.Runtime. InteropServices ;
namespace ZM7
{
/// <summary>
/// Summary description for AMS.
/// </summary>
public class AMS
{
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")]
public static extern int z4open(); //another function from the dll
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")] /* Do I need to use
DllImport for every fiunction I'm using? */
public static extern byte[] z4date();
...

public byte[] getDate()
{
Byte[] myDate;
myDate = new Byte[8];
myDate = z4date(); //function call where I receive error "Can not
marshal return value"
return myDate();
}

Any help is appreciated.

Nov 15 '05 #2
Hi Angel,
If your have *z4date* returning a string. How do you expect PInvoke to
marshal it as an array of bytes
Instead of declare the function as:
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")]
public static extern byte[] z4date();

try to declare it as:
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")]
public static extern string z4date();

If you need that byte array you should convert the string to that array. We
cannot expect the marshaler to convert from any to any type we want.
Yes, you have to use DllImport for each and any function that you import
from unmanaged library.
--
HTH
B\rgds
100

"Angel" <none> wrote in message
news:u5******** ******@tk2msftn gp13.phx.gbl...
Hi again,
I'm trying to call functions from a proprietary DLL but it's turned out to
be more difficult than I thought.

I have this W32.DLL which was written in C by USPS. They don't provide the
code so I only have the documentation.
I'm trying to call a function called z4date that, according to the docs,
returns the date as "an 8-byte character string in the "YYYYMMDD" format".
When I run it with this code I've written , I get "Can not marshal return
value".

My real concern is that, if I'm having trouble with these functions that
return simple data types, how am I going to interact with functions that
return user-defined data types?

This is what I've written in the class so far:

...
using System.Runtime. InteropServices ;
namespace ZM7
{
/// <summary>
/// Summary description for AMS.
/// </summary>
public class AMS
{
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")]
public static extern int z4open(); //another function from the dll
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")] /* Do I need to use
DllImport for every fiunction I'm using? */
public static extern byte[] z4date();
...

public byte[] getDate()
{
Byte[] myDate;
myDate = new Byte[8];
myDate = z4date(); //function call where I receive error "Can not
marshal return value"
return myDate();
}

Any help is appreciated.

Nov 15 '05 #3
Stoitcho,

The problem with declaring the return value as a string is that the
memory allocated on the heap for the string in the unmanaged realm will now
not be released correctly, and cause a memory leak.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Stoitcho Goutsev (100) [C# MVP]" <10*@100.com> wrote in message
news:eL******** ******@TK2MSFTN GP10.phx.gbl...
Hi Angel,
If your have *z4date* returning a string. How do you expect PInvoke to
marshal it as an array of bytes
Instead of declare the function as:
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")]
public static extern byte[] z4date();

try to declare it as:
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")]
public static extern string z4date();

If you need that byte array you should convert the string to that array. We cannot expect the marshaler to convert from any to any type we want.
Yes, you have to use DllImport for each and any function that you import
from unmanaged library.
--
HTH
B\rgds
100

"Angel" <none> wrote in message
news:u5******** ******@tk2msftn gp13.phx.gbl...
Hi again,
I'm trying to call functions from a proprietary DLL but it's turned out to be more difficult than I thought.

I have this W32.DLL which was written in C by USPS. They don't provide the code so I only have the documentation.
I'm trying to call a function called z4date that, according to the docs,
returns the date as "an 8-byte character string in the "YYYYMMDD" format". When I run it with this code I've written , I get "Can not marshal return value".

My real concern is that, if I'm having trouble with these functions that
return simple data types, how am I going to interact with functions that
return user-defined data types?

This is what I've written in the class so far:

...
using System.Runtime. InteropServices ;
namespace ZM7
{
/// <summary>
/// Summary description for AMS.
/// </summary>
public class AMS
{
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")]
public static extern int z4open(); //another function from the dll
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")] /* Do I need to use
DllImport for every fiunction I'm using? */
public static extern byte[] z4date();
...

public byte[] getDate()
{
Byte[] myDate;
myDate = new Byte[8];
myDate = z4date(); //function call where I receive error "Can not marshal return value"
return myDate();
}

Any help is appreciated.


Nov 15 '05 #4
I had tried it before but I kept getting "Object reference not set to an
instance of an object" when I moved the return value of the function to a
string variable.I tried it without the static modifier and got the same
results.

[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")]

public static extern string z4date();

....

public static string getDate()

{

string mystr;

mystr = z4date(); // error: Object reference not set to an instance
of an object

return mystr;

}

I'm trying with Nicholas' suggestion to see if it works.
Thanks.
"Stoitcho Goutsev (100) [C# MVP]" <10*@100.com> wrote in message
news:eL******** ******@TK2MSFTN GP10.phx.gbl...
Hi Angel,
If your have *z4date* returning a string. How do you expect PInvoke to
marshal it as an array of bytes
Instead of declare the function as:
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")]
public static extern byte[] z4date();

try to declare it as:
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")]
public static extern string z4date();

If you need that byte array you should convert the string to that array. We cannot expect the marshaler to convert from any to any type we want.
Yes, you have to use DllImport for each and any function that you import
from unmanaged library.
--
HTH
B\rgds
100

"Angel" <none> wrote in message
news:u5******** ******@tk2msftn gp13.phx.gbl...
Hi again,
I'm trying to call functions from a proprietary DLL but it's turned out to be more difficult than I thought.

I have this W32.DLL which was written in C by USPS. They don't provide the code so I only have the documentation.
I'm trying to call a function called z4date that, according to the docs,
returns the date as "an 8-byte character string in the "YYYYMMDD" format". When I run it with this code I've written , I get "Can not marshal return value".

My real concern is that, if I'm having trouble with these functions that
return simple data types, how am I going to interact with functions that
return user-defined data types?

This is what I've written in the class so far:

...
using System.Runtime. InteropServices ;
namespace ZM7
{
/// <summary>
/// Summary description for AMS.
/// </summary>
public class AMS
{
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")]
public static extern int z4open(); //another function from the dll
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")] /* Do I need to use
DllImport for every fiunction I'm using? */
public static extern byte[] z4date();
...

public byte[] getDate()
{
Byte[] myDate;
myDate = new Byte[8];
myDate = z4date(); //function call where I receive error "Can not marshal return value"
return myDate();
}

Any help is appreciated.


Nov 15 '05 #5
Thanks for the help.
I think I understand what you're saying but since I'm pretty new with this
type of programming, how would that look like?
So far, I have:

[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")]
public static extern IntPtr z4date();

....

public static IntPtr getDate()

{

IntPtr ptr ;

ptr = z4date(); // ptr.ToString() = "2"

string str = Marshal.PtrToSt ringAnsi(ptr);

MessageBox.Show (str); //str is null

return str;

}

But the debugger tells me that str is null, so I know I'm doing something
wrong. If I don't move it to a string (eg. MessageBox.Show
(ptr.ToString() );), it displays a "2".

Angel



"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c om> wrote in
message news:ul******** *****@TK2MSFTNG P11.phx.gbl...
Angel,

You will not be able to do this. The reason that it doesn't work with
your definitions is because the pointer that is being returned by the
function is of an indeterminate nature. True, the documentation states that it returns eight bytes, but there is nothing in the code that indicates that is the case.

To get around this, you should declare your return type as an IntPtr,
and then pass that to the static PtrToStringAnsi method on the Marshal
class.

The only thing to be considerate of is the fact that the function
allocated memory and returned it. To prevent a leak, you will have to
dispose of the memory pointed to by the IntPtr. How you do this is
dependent on how the DLL allocates it, and will require another call through P/Invoke.

Also, you do have to use the attribute for every declaration.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Angel" <none> wrote in message
news:u5******** ******@tk2msftn gp13.phx.gbl...
Hi again,
I'm trying to call functions from a proprietary DLL but it's turned out to be more difficult than I thought.

I have this W32.DLL which was written in C by USPS. They don't provide the code so I only have the documentation.
I'm trying to call a function called z4date that, according to the docs,
returns the date as "an 8-byte character string in the "YYYYMMDD" format". When I run it with this code I've written , I get "Can not marshal return value".

My real concern is that, if I'm having trouble with these functions that
return simple data types, how am I going to interact with functions that
return user-defined data types?

This is what I've written in the class so far:

...
using System.Runtime. InteropServices ;
namespace ZM7
{
/// <summary>
/// Summary description for AMS.
/// </summary>
public class AMS
{
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")]
public static extern int z4open(); //another function from the dll
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")] /* Do I need to use
DllImport for every fiunction I'm using? */
public static extern byte[] z4date();
...

public byte[] getDate()
{
Byte[] myDate;
myDate = new Byte[8];
myDate = z4date(); //function call where I receive error "Can not marshal return value"
return myDate();
}

Any help is appreciated.


Nov 15 '05 #6

"Angel" <none> wrote in message
news:u5******** ******@tk2msftn gp13.phx.gbl...
Hi again,
I'm trying to call functions from a proprietary DLL but it's turned out to
be more difficult than I thought.

I have this W32.DLL which was written in C by USPS. They don't provide the
code so I only have the documentation.
I'm trying to call a function called z4date that, according to the docs,
returns the date as "an 8-byte character string in the "YYYYMMDD" format".
When I run it with this code I've written , I get "Can not marshal return
value".

My real concern is that, if I'm having trouble with these functions that
return simple data types, how am I going to interact with functions that
return user-defined data types?

This is what I've written in the class so far:

...
using System.Runtime. InteropServices ;
namespace ZM7
{
/// <summary>
/// Summary description for AMS.
/// </summary>
public class AMS
{
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")]
public static extern int z4open(); //another function from the dll
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")] /* Do I need to use
DllImport for every fiunction I'm using? */
public static extern byte[] z4date();
...

public byte[] getDate()
{
Byte[] myDate;
myDate = new Byte[8];
myDate = z4date(); //function call where I receive error "Can not
marshal return value"
return myDate();
}

Any help is appreciated.


Just go one step further and encapsulate calling your "C" functions within a
C++ managed wrapper class. Use that class to 'interact' with the rest of
your C# application. Remove your imports from your class above and place
them within the module/namespace. Create methods that then call your
external "C" functions.

The only real way to remain sane is to isolate the CTS from the C types and
don't try to half step. <g>

Question, is the DLL really written in 'C' and therefore using a cdecl
calling convention, or is it written using stdcall (a la Win API)? If you
are really accessing exported C then you have to use the extern "C"
attribute.

-ralph


Nov 15 '05 #7
Hi Nicholas,
You are right. It frees only memory allocated with CoTaskMemAlloc.
--
B\rgds
100

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard .caspershouse.c om> wrote in
message news:ub******** ******@TK2MSFTN GP10.phx.gbl...
Stoitcho,

The problem with declaring the return value as a string is that the
memory allocated on the heap for the string in the unmanaged realm will now not be released correctly, and cause a memory leak.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m

"Stoitcho Goutsev (100) [C# MVP]" <10*@100.com> wrote in message
news:eL******** ******@TK2MSFTN GP10.phx.gbl...
Hi Angel,
If your have *z4date* returning a string. How do you expect PInvoke to
marshal it as an array of bytes
Instead of declare the function as:
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")]
public static extern byte[] z4date();

try to declare it as:
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")]
public static extern string z4date();

If you need that byte array you should convert the string to that array. We
cannot expect the marshaler to convert from any to any type we want.
Yes, you have to use DllImport for each and any function that you import
from unmanaged library.
--
HTH
B\rgds
100

"Angel" <none> wrote in message
news:u5******** ******@tk2msftn gp13.phx.gbl...
Hi again,
I'm trying to call functions from a proprietary DLL but it's turned out to
be more difficult than I thought.

I have this W32.DLL which was written in C by USPS. They don't provide the code so I only have the documentation.
I'm trying to call a function called z4date that, according to the
docs, returns the date as "an 8-byte character string in the "YYYYMMDD"

format". When I run it with this code I've written , I get "Can not marshal return value".

My real concern is that, if I'm having trouble with these functions that return simple data types, how am I going to interact with functions that return user-defined data types?

This is what I've written in the class so far:

...
using System.Runtime. InteropServices ;
namespace ZM7
{
/// <summary>
/// Summary description for AMS.
/// </summary>
public class AMS
{
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")]
public static extern int z4open(); //another function from the dll
[DllImport("C:\\ zm7\\Developm\\ DLL\\W32.DLL")] /* Do I need to use DllImport for every fiunction I'm using? */
public static extern byte[] z4date();
...

public byte[] getDate()
{
Byte[] myDate;
myDate = new Byte[8];
myDate = z4date(); //function call where I receive error "Can not marshal return value"
return myDate();
}

Any help is appreciated.



Nov 15 '05 #8

Hi Angel,

Thanks for posting in this community!!

I am monitoring this group. After reviewing your discussion in this post, I
think you meet the problem of P/invoke marshal.

I think you should follow Nicholas's suggestion to marshal the return value
as IntPtr. But, I think you may can not use Marshal.PtrToSt ringAnsi to
convert the value. Because the return value of z4date may be a character
array without a '\0' at the end of the array. So maybe you should read the
byte one by one(Use Marshal.ReadByt e method). Like this:

//Test C function, which return value without a '\0' at the end of the
character array:
extern "C" __declspec(dlle xport) char* RetAChar()
{
pChar = new char[8];
for(int i=0; i<=7; i++)
{
*pChar = 'd';
pChar++;
}
pChar -= 8;
return pChar;
}

[DllImport("DllD emo.dll", CharSet=CharSet .Ansi)]
private static extern IntPtr RetAChar();
private void button3_Click(o bject sender, System.EventArg s e)
{
IntPtr str=RetAChar();

byte b;
for(int i=0;i<8;i++)
{
b=Marshal.ReadB yte(str);
Console.WriteLi ne(Convert.ToCh ar(b));
}
}

But as you stated, your problem should not related to this, can you show me
more information of your problem?

=============== =============== ======
Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Nov 15 '05 #9
Hi Angel,

Does my reply make sense to you?

Is your problem resolved? Please feel free to feedback. Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Nov 15 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
2745
by: Jim Hubbard | last post by:
I have some C# code that is supposed to wrap the defrag APIs and I am trying to convert it to VB.Net (2003). But, I keep having problems. The C# code is relatively short, so I'll post it here..... -------- // // a set of simple C# wrappers over the NT Defragmenter APIs //
8
5455
by: baustin75 | last post by:
Posted: Mon Oct 03, 2005 1:41 pm Post subject: cannot mail() in ie only when debugging in php designer 2005 -------------------------------------------------------------------------------- Hello, I have a very simple problem but cannot seem to figure it out. I have a very simple php script that sends a test email to myself. When I...
1
4195
by: dhornyak | last post by:
I have been banging my head against the wall for a while now, and can't seem to id the problem. I've been through a ton of posts and the code doesn't seem any different. Can anybody see it? When I call to GetTokenInformation I receive a buffer size (see //HERE... comment in code), but when I let the code continue, asp.net just sits there...
8
1948
by: Berhack | last post by:
I am not too familiar with C# interop so please help me out. I need to call the following C function (in a DLL): // this creates an array of strings // LPTSTR is just char * void C_Func(LPTSTR **pszStrings) { (*pszStrings) = reinterpret_cast<LPTSTR *>(malloc(2 * sizeof(LPTSTR))); (*pszStrings) = _T("A test");
5
2294
by: SStory | last post by:
Hi all, I really needed to get the icons associated with each file that I want to show in a listview. I used the follow modified code sniplets found on the internet. I have left in commented code for anyone else who may be looking to do the same.
1
3696
by: Rahul | last post by:
Hi Everybody I have some problem in my script. please help me. This is script file. I have one *.inq file. I want run this script in XML files. But this script errors shows . If u want i am attach this script files and inq files. I cant understand this error. Please suggest me. You can talk with my yahoo id b_sahoo1@yahoo.com. Now i am...
22
9202
by: SQACSharp | last post by:
I'm trying to get the control name of an editbox in another window. The following code set the value "MyPassword" in the password EditBox but it fail to return the control name of the EditBox. I'm sure the problem is the way i'm using the sendmessage API, the return string and the lParam return 0....is anybody have a clue? any sendmessage...
15
2560
by: Jay | last post by:
I have a multi threaded VB.NET application (4 threads) that I use to send text messages to many, many employees via system.timer at a 5 second interval. Basically, I look in a SQL table (queue) to determine who needs to receive the text message then send the message to the address. Only problem is, the employee may receive up to 4 of the...
8
2922
by: =?Utf-8?B?UHVjY2E=?= | last post by:
Hi, I'm using vs2005, .net 2, C# for Windows application. I use DllImport so I can call up a function written in C++ as unmanaged code and compiled as a dll us vs2005. My application is able to call the function, EncodeAsnUser. And it's returning OK but when I display the decoded data in another part of my application it shows no data has...
0
7475
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7664
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
1
7436
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
7766
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
5981
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
1
5341
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
3463
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
1
1022
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
715
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.