Вызывать или вызывать консольное приложение C # из веб-службы C #? - PullRequest
2 голосов
/ 17 августа 2011

Из-за моей проблемы с тем, что я не могу запустить команду dos через мой веб-сервис.

C # веб-сервис запускает пакетный файл или команду dos?

Так как яя не могу заставить мой веб-сервис запускать команду dos напрямую, сейчас я думаю о создании консольного приложения C #, которое будет запускать мою команду dos, затем консольное приложение будет вызываться веб-сервисом.

Возможно ли это сделать?

Ответы [ 2 ]

4 голосов
/ 17 августа 2011

Если это возможно из веб-службы, вам необходимо выполнить одно из двух действий:

  • Использовать олицетворение для запуска консольного приложения
  • Использовать учетную запись в IISкоторый может выполнить приложение.

Предполагая, что один из вышеперечисленных работает, и вы можете запустить консольное приложение, есть также несколько других вещей, которые вам нужно изучить:

  • Возможно, вам потребуется изменить разрешения на выполнение на вкладке Домашний каталог в IIS
  • Возможно, вам придется отключить диалоговое окно консоли, так как это может вызвать некоторые флаги

Я должен был сделать это однажды, и стандартное подражание мне не помогло.Я должен был обращаться с подражанием немного по-другому.Я не знаю, столкнетесь ли вы с теми же препятствиями, что и я, но вот класс, который я создал для программного подражания через API Windows:

РЕДАКТИРОВАТЬ

Изменен класс экземпляров, реализующий IDisposable - спасибо @John Saunders

Добавлен перегруженный конструктор для упрощения реализации с использованием оператора и добавлено логическое свойство Impersonating, чтобы проверить, является ли экземпляр в настоящее время олицетворением.Существуют также методы BeginImpersonationContext и EndImpersonationContext для альтернативного использования.

/// <summary>
/// Leverages the Windows API (advapi32.dll) to programmatically impersonate a user.
/// </summary>
public class ImpersonationContext : IDisposable
{
    #region constants

    private const int LOGON32_LOGON_INTERACTIVE = 2;
    private const int LOGON32_PROVIDER_DEFAULT = 0;

    #endregion

    #region global variables

    private WindowsImpersonationContext impersonationContext;
    private bool impersonating;

    #endregion

    #region unmanaged code

    [DllImport("advapi32.dll")]
    private static extern int LogonUserA(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken);

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool RevertToSelf();

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    private static extern bool CloseHandle(IntPtr handle);

    #endregion

    #region constructors

    public ImpersonationContext()
    {
        impersonating = false;
    }

    /// <summary>
    /// Overloaded constructor and begins impersonating.
    /// </summary>
    public ImpersonationContext(string userName, string password, string domain)
    {
        this.BeginImpersonationContext(userName, password, domain);
    }

    #endregion

    #region impersonation methods

    /// <summary>
    /// Begins the impersonation context for the specified user.
    /// </summary>
    /// <remarks>Don't call this method if you used the overloaded constructor.</remarks>
    public void BeginImpersonationContext(string userName, string password, string domain)
    {
        //initialize token and duplicate variables
        IntPtr token = IntPtr.Zero;
        IntPtr tokenDuplicate = IntPtr.Zero;

        if (RevertToSelf())
        {
            if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0)
            {
                if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                {
                    using (WindowsIdentity tempWindowsIdentity = new WindowsIdentity(tokenDuplicate))
                    {
                        //begin the impersonation context and mark impersonating true
                        impersonationContext = tempWindowsIdentity.Impersonate();
                        impersonating = true;
                    }
                }
            }
        }

        //close the handle to the account token
        if (token != IntPtr.Zero)
            CloseHandle(token);

        //close the handle to the duplicated account token
        if (tokenDuplicate != IntPtr.Zero)
            CloseHandle(tokenDuplicate);
    }

    /// <summary>
    /// Ends the current impersonation context.
    /// </summary>
    public void EndImpersonationContext()
    {
        //if the context exists undo it and dispose of the object
        if (impersonationContext != null)
        {
            //end the impersonation context and dispose of the object
            impersonationContext.Undo();
            impersonationContext.Dispose();
        }

        //mark the impersonation flag false
        impersonating = false;
    }

    #endregion

    #region properties

    /// <summary>
    /// Gets a value indicating whether the impersonation is currently active.
    /// </summary>
    public bool Impersonating
    {
        get
        {
            return impersonating;
        }
    }

    #endregion

    #region IDisposable implementation

    ~ImpersonationContext()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);               
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (impersonationContext != null)
            {
                impersonationContext.Undo();
                impersonationContext.Dispose();
            }
        }
    }

    #endregion    
}

EDIT

Наконец, вот пример того, как реализовать класс:

using (ImpersonationContext context = new ImpersonationContext("user", "password", "domain"))
{
    if (context.Impersonating)
    {
        Process.Start(@"/Support/SendFax/SendFax.exe");
    }
}
1 голос
/ 17 августа 2011

Самый простой метод вызова консольного приложения .Net из другого приложения .Net - это связать сборку и напрямую вызвать статический метод Main. Но если есть какая-то причина, по которой вы не можете выполнять команды (разрешения), у вас будут те же проблемы с этим методом.

Если проблема связана с разрешениями, вы можете:

  • Изменение учетной записи, используемой ASP.Net для размещения вашего веб-сервиса
  • Создайте службу Windows, на которой размещен прослушиватель WCF или .Net Remoting. Разработайте слушатель для запуска процессов, которые вам нужно запустить. Запустите эту службу с необходимыми разрешениями

Кроме того, как упоминал Джон Калберер, это может быть связано с неспособностью этих служб взаимодействовать с рабочим столом. Если это проблема, , тогда посмотрите этот вопрос .

...