从.NET调用非托管代码

我正在尝试在我的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。 它正在运行,但它说

句柄无效

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

也许您可以使用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所以我无法测试这种情况。

也许有关RUNDLL32.EXE的Microsoft文档会有帮助吗? 特别是,这一节似乎很有用:

Rundll入口点的参数如下:

    hwnd  - 应该用作所有者窗口的窗口句柄
          你的DLL创建的任何窗口
    hinst  - 你的DLL的实例句柄
    lpszCmdLine  - 您的DLL应该解析的ASCIIZ命令行
    nCmdShow  - 描述了如何显示DLL的窗口

在以下示例中:

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

Rundll会调用Setupx.dll中的InstallHinfSection()入口点函数并将其传递给以下参数:

    hwnd =(父窗口句柄)
    hinst = SETUPX.DLL的HINSTANCE
    lpszCmdLine =“132 C:\ WINDOWS \ INF \ SHELL.INF”
    nCmdShow =(无论nCmdShow传递给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,但根据pinvoke.net ,SW_SHOWNORMAL的值为1,这可能是你想要的。

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