Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
561 views
in Technique[技术] by (71.8m points)

asp.net - Invoke or call C# console app from C# web service?

Due to my problem that I am unable to run dos command via my web service.

C# web service running batch file or dos command?

Since I cannot make my web service run dos command directly, I am now thinking about creating C# console app that will run my dos command, then the console app will be invoked by web service.

Is it possible to do so?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If it's possible from within a web service, you'll need to do one of two things:

  • Use impersonation to execute the console application
  • Use an account in IIS that can execute the application.

Assuming that one of the above works and you're able to execute the console app, there are also a few other things you'll need to look into:

  • You may need to change the execute permissions under the Home Directory tab in IIS
  • You may need to suppress the console dialog, as this may raise some flags

I had to do this once before, and standard impersonation didn't work for me. I had to handle impersonation a little differently. I don't know if you'll run into the same obstacles that I did, but here is a class that I created for impersonating programmatically through the Windows API:

EDIT

Changed to an instance class implementing IDisposable - thanks @John Saunders

Added an overloaded constructor for easier implementation with using statement, and added boolean property Impersonating to check whether the instance is currently impersonating. There are also BeginImpersonationContext and EndImpersonationContext methods for alternative use.

/// <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

Lastly, here is an example of how to implement the class:

using (ImpersonationContext context = new ImpersonationContext("user", "password", "domain"))
{
    if (context.Impersonating)
    {
        Process.Start(@"/Support/SendFax/SendFax.exe");
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...