[英]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.由于我的问题,我无法通过我的 web 服务运行 dos 命令。
C# web service running batch file or dos command? C# web 服务运行批处理文件或dos命令?
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.由于我不能让我的 web 服务直接运行 dos 命令,我现在正在考虑创建 C# 控制台应用程序来运行我的 dos 命令,然后控制台应用程序将由 Z2567A5EC9705EB7AC2C984033E0618 调用
Is it possible to do so?有可能这样做吗?
If it's possible from within a web service, you'll need to do one of two things:如果可以从 web 服务中实现,则需要执行以下两项操作之一:
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:假设上述其中一项有效并且您能够执行控制台应用程序,那么您还需要研究其他一些事项:
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:我不知道您是否会遇到与我相同的障碍,但这是我创建的 class,用于通过 Windows API 以编程方式模拟:
EDIT编辑
Changed to an instance class implementing IDisposable - thanks @John Saunders更改为实现 IDisposable 的实例 class - 感谢@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.添加了一个重载的构造函数以便于使用 using 语句实现,并添加了 boolean 属性 Impersonating 以检查实例当前是否正在模拟。 There are also BeginImpersonationContext and EndImpersonationContext methods for alternative use.还有 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编辑
Lastly, here is an example of how to implement the class:最后,这是一个如何实现 class 的示例:
using (ImpersonationContext context = new ImpersonationContext("user", "password", "domain"))
{
if (context.Impersonating)
{
Process.Start(@"/Support/SendFax/SendFax.exe");
}
}
The easiest method to call a.Net console application from another.Net application is to link in the assembly, and invoke the static Main
method directly.从另一个.Net 应用程序调用一个.Net 控制台应用程序的最简单方法是在程序集中进行链接,然后直接调用 static Main
方法。 But if there is any reason you can't execute commands (permissions), then you'll have the same problems with this method.但是,如果有任何原因您无法执行命令(权限),那么您将遇到与此方法相同的问题。
If permissions are the problem, then you could:如果权限是问题,那么您可以:
Also, as John Kalberer mentioned, it could be related to the inability of these services to interact with the desktop.此外,正如 John Kalberer 所提到的,这可能与这些服务无法与桌面交互有关。 If this is the problem, then see this question .如果这是问题, 请参阅此问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.