从.NET调用非托管代码

时间:2010-04-08 17:12:26

标签: c# dll unmanaged

我正在尝试在我的c#程序中使用dll,但我似乎无法让它工作。我已经制作了如下所示的测试应用程序。返回值为0,但它实际上并没有按预期执行。

以下命令确实有效:

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"

代码:

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));
        }
    }
}

这是dumpbin / exports命令的内容

File Type: DLL

  Section contains the following exports for cmproxy.dll

    00000000 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

当它工作时,它为VPN连接设置代理服务器。

修改

我希望避免从system.process

运行rundll32

我还可以提供dll和我的测试应用程序的链接。虽然上面粘贴的代码是它包含的所有内容,但我认为可以从服务器资源工具包中获取dll。

更新

我已经用c ++编写了一个测试DLL,它简单地回应了它给出的args。它正在运行,但它说

  

句柄无效

3 个答案:

答案 0 :(得分:0)

只是一些值得思考的东西。这可能是一种可能的解决方法。

也许您可以使用System.Diagnostics.Process类从代码中运行命令,如下所示:

  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();

如果需要在运行时替换某些参数,那么可以使用String.Format格式化参数并替换所需的任何内容。

编辑1:

这里似乎没有正确突出显示代码。我没有cmproxy.dll所以我无法测试这种情况。

答案 1 :(得分:0)

也许Microsoft documentation on RUNDLL32.EXE会有所帮助?特别是,这一节似乎很有用:

  

Rundll条目的参数   要点如下:

   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
     

在以下示例中:

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

Rundll会调用InstallHinfSection()入口点   在Setupx.dll中运行并传递它   以下参数:

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

更新2

这应该适合你:

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

然后将其称为:

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

我使用shell32.dll中的Control_RunDLL入口点测试了相同的代码,我可以确认它对我来说没问题。诀窍是获取正确的HWND和HINSTANCE指针作为前两个参数传入。此外,我之前为nCmdShow传递了0,但是according to pinvoke.net,SW_SHOWNORMAL的值为1,这可能是你想要的。

答案 2 :(得分:0)

答案是CharSet = CharSet.Unicode应该是CharSet = CharSet.Ansi