开发者

Calling unmanaged code from .NET

I am trying to use a dll in my c# program but I just cant seem to get it to work. I have made a test app shown below. The return value is 0, however it does not actually do what it is supposed to do.

Whereas the following command does work:

rundll32 cmproxy.dll,SetProxy /source_filename proxy-1.txt /backup_filename roxy.bak /DialRasEntry NULL /TunnelRasEntry DSLVPN /Profile "C:\Documents and ettings\Administrator\Application Data\Microsoft\Network\Connections\Cm\dslvpn.cmp"

Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
using System.Net;
using WUApiLib;

namespace nac
{
    class Program
    {
        [DllImport("cmproxy.dll", CharSet = CharSet.Unicode)]
        static extern int SetProxy(string cmdLine);

        static void Main(string[] args)
        {
            string cmdLine = @"/source_filename proxy-1.txt /backup_filename proxy.bak /DialRasEntry NULL /TunnelRasEntry DSLVPN /Profile ""C:\Documents and Settings\Administrator\Application Data\Microsoft\Network\Connections\Cm\dslvpn.cmp""";
            Console.WriteLine(SetProxy(cmdLine));
        }
    }
}

Here is the contents of the dumpbin /exports command

File Type: DLL

  Section contains the following exports for cmproxy.dll

    00开发者_如何学编程000000 characteristics
    3E7FEF8C time date stamp Tue Mar 25 05:56:28 2003
        0.00 version
           1 ordinal base
           1 number of functions
           1 number of names

    ordinal hint RVA      name

          1    0 00001B68 SetProxy

  Summary

        1000 .data
        1000 .reloc
        1000 .rsrc
        2000 .text

When this works it sets the proxy server for a VPN connection.

EDIT:

I wish to avoid running rundll32 from system.process

I can also provide a link to both the dll and my test app. Although the code pasted above is all it contains and the dll is available from the Server resource kit I think.

UPDATE:

I have written a test DLL in c++ that simply echos the args it is given. It is running but it says

The handle is invalid


Just some food for thought. This may be a possible work around.

Perhaps you could use the System.Diagnostics.Process class to run the command from your code like this:

  System.Diagnostics.Process p = new System.Diagnostics.Process();
  p.StartInfo.Arguments = @"cmproxy.dll,SetProxy /source_filename proxy-1.txt /backup_filename roxy.bak /DialRasEntry NULL /TunnelRasEntry DSLVPN /Profile ""C:\Documents and ettings\Administrator\Application Data\Microsoft\Network\Connections\Cm\dslvpn.cmp\""";
  p.StartInfo.FileName = "rundll32";
  p.Start();

If you need to substitute some of the arguments at runtime then you could use String.Format to format the arguments and substitute whatever you need.

Edit 1:

It doesn't seem to be correctly highlighting the code here. I don't have cmproxy.dll so I cannot test this scenario.


Perhaps the Microsoft documentation on RUNDLL32.EXE would be helpful? In particular, this section seems useful:

The parameters to the Rundll entry point are as follows:

   hwnd - window handle that should be used as the owner window for
          any windows your DLL creates
   hinst - your DLL's instance handle
   lpszCmdLine - ASCIIZ command line your DLL should parse
   nCmdShow - describes how your DLL's windows should be displayed

In the following example:

     RUNDLL.EXE SETUPX.DLL,InstallHinfSection 132 C:\WINDOWS\INF\SHELL.INF

Rundll would call the InstallHinfSection() entrypoint function in Setupx.dll and pass it the following parameters:

   hwnd = (parent window handle)
   hinst = HINSTANCE of SETUPX.DLL
   lpszCmdLine = "132 C:\WINDOWS\INF\SHELL.INF"
   nCmdShow = (whatever the nCmdShow was passed to CreateProcess)

Update 2:

This should work for you:

[DllImport("cmproxy.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
static extern void SetProxy(IntPtr hwnd, IntPtr hinst, string lpszCmdLine, int nCmdShow);

and then call it like:

const int SW_SHOWNORMAL = 1;
IntPtr hWnd = (this as Form).Handle;
IntPtr hInstance = Marshal.GetHINSTANCE(this.GetType().Module);
SetProxy(hWnd, hInstance, cmdLine, SW_SHOWNORMAL);

I tested the same code with the Control_RunDLL entrypoint in shell32.dll and I can confirm that it works fine for me. The trick is getting the correct HWND and HINSTANCE pointers to pass in as the first two arguments. Also, I was previously passing 0 for the nCmdShow, but according to pinvoke.net, SW_SHOWNORMAL has value 1, which is probably what you want.


The answer is CharSet = CharSet.Unicode should be CharSet = CharSet.Ansi

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜