Вызов неуправляемого кода из .NET - PullRequest
2 голосов
/ 08 апреля 2010

Я пытаюсь использовать dll в моей программе на c #, но я просто не могу заставить ее работать. Я сделал тестовое приложение, показанное ниже. Возвращаемое значение равно 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.

EDIT:

Я хочу избежать запуска rundll32 из system.process

Я также могу предоставить ссылку как на dll, так и на мое тестовое приложение. Хотя код, вставленный выше, это все, что он содержит, и я думаю, что dll доступна из набора ресурсов сервера.

UPDATE:

Я написал тестовую DLL на c ++, которая просто повторяет аргументы, которые ему даны. Он работает, но он говорит

Неверный дескриптор

Ответы [ 3 ]

0 голосов
/ 09 апреля 2010

Возможно, будет полезна документация Microsoft на RUNDLL32.EXE ? В частности, этот раздел кажется полезным:

Параметры записи Рандля Дело в следующем:

   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

Рандлл вызовет точку входа 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);

Я тестировал тот же код с точкой входа Control_RunDLL в shell32.dll, и я могу подтвердить, что он работает нормально для меня. Хитрость заключается в получении правильных указателей HWND и HINSTANCE для передачи в качестве первых двух аргументов. Кроме того, я ранее передавал 0 для nCmdShow, но в соответствии с pinvoke.net , SW_SHOWNORMAL имеет значение 1, что, вероятно, то, что вы хотите.

0 голосов
/ 14 апреля 2010

Ответ - CharSet = CharSet. Юникод должен быть CharSet = CharSet.Ansi

.
0 голосов
/ 09 апреля 2010

Просто пища для размышлений. Это может быть возможным обходным путем.

Возможно, вы могли бы использовать класс 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, поэтому я не могу проверить этот сценарий.

...