从 .NET 调用非托管代码

发布于 2024-08-28 07:56:59 字数 1905 浏览 8 评论 0原文

我正在尝试在我的 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,它只是回显给定的参数。它正在运行,但它说

句柄无效

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

    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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

笨笨の傻瓜 2024-09-04 07:56:59

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

也许您可以使用 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,因此无法测试此场景。

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.

欢你一世 2024-09-04 07:56:59

也许 有关 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 将调用 InstallHinfSection() 入口点 Setupx.dll 中的函数并将其传递给 以下参数:

 hwnd = (父窗口句柄)
   hinst = SETUPX.DLL 的实例
   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< /a>,SW_SHOWNORMAL 的值为 1,这可能就是您想要的。

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.

若水般的淡然安静女子 2024-09-04 07:56:59

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文