[英]C#: ShortCut and Impersonation
I have a problem creating a shortcut on a server. 我在服务器上创建快捷方式时遇到问题。 It always throw an exception:
它总是抛出异常:
Access denied.
拒绝访问。 0x80070005
0x80070005
I really don't know if the problem happens because the shortcut location or the shortcut target. 我真的不知道是否由于快捷方式位置或快捷方式目标而发生问题。
I have to use Impersonation to access the file system. 我必须使用模拟来访问文件系统。 Using
IO.File
and IO.Directory
I can create directorys, copy and remove files, etc... without any problem. 使用
IO.File
和IO.Directory
我可以创建目录,复制和删除文件等,而没有任何问题。 Also, If I open a remote desktop to the file repository, with the impersonate user, i can create the shortcut with any problems. 另外,如果我用模拟用户打开文件存储库的远程桌面,则可以创建有任何问题的快捷方式。
However for creating a shortcut I'm using WHSell, and it seems it has some problems with impersonation. 但是,对于创建快捷方式,我正在使用WHSell,并且似乎在模拟方面存在一些问题。 Any ideas?
有任何想法吗?
This is my code: 这是我的代码:
#region Impersonation
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
[DllImport("advapi32.dll")]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
private void LogonAsUser(String userName, String domain, String password)
{
if (!LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out safeTokenHandle))
{
int ret = Marshal.GetLastWin32Error();
throw new System.ComponentModel.Win32Exception(ret);
}
}
private void LogonAsUserEnd(IntPtr token)
{
if (!IntPtr.Equals(token, IntPtr.Zero))
{
CloseHandle(token);
}
}
public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeTokenHandle()
: base(true)
{
}
[DllImport("kernel32.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr handle);
protected override bool ReleaseHandle()
{
return CloseHandle(handle);
}
}
#endregion
private void CreateShortCut(string shorcutPath, string shortcutTarget)
{
IWshRuntimeLibrary.WshShell wshShell = new IWshRuntimeLibrary.WshShell();
IWshRuntimeLibrary.IWshShortcut shortcut;
shortcut = (IWshRuntimeLibrary.IWshShortcut)wshShell.CreateShortcut(shorcutPath);
shortcut.TargetPath = shortcutTarget;
shortcut.WorkingDirectory = shorcutPath;
shortcut.Description = "Presupuestos del servicio";
shortcut.Save();
}
public void CreateServicioRepository(presupuestos p)
{
LogonAsUser(userName, domain, password);
using (safeTokenHandle)
{
using (WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle()))
{
using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
{
try
{
if (Directory.Exists(serviceBasePath)) // serviceBasePath = "\\myserver\myfolder"
{
//Creamos el directorio para el servicio
string year = p.Fecha_alta.Year.ToString();
string serviceFolderName = p.Codigo + "_" + p.productos.Siglas;
if (p.IdObra.HasValue) serviceFolderName += "_" + p.obras.TituloCorto;
serviceFolderName = formatePath(serviceFolderName);
string servicePaht = Path.Combine(serviceBasePath, year, serviceFolderName);
if (!Directory.Exists(servicePaht)) Directory.CreateDirectory(servicePaht);
//Comprobamos que existe la carpeta de backend de los informes
string presupuestosFolder = getPresupuestoReporthPath(p); //persupuestosFolder = "\\anotherServer\anotherfolder
if (!Directory.Exists(presupuestosFolder)) Directory.CreateDirectory(presupuestosFolder);
//Creamos el acceso directo a la carpeta de informes generados en presupuesto
if (!string.IsNullOrWhiteSpace(presupuestosFolder))
{
string shortCutName = "001_" + p.Codigo + "_Presupuesto.lnk";
string shortCutPath = Path.Combine(servicePaht, shortCutName);
if (!File.Exists(shortCutPath)) CreateShortCut(shortCutPath, presupuestosFolder);
}
//Comprobamos que existe la carpeta de backend de los informes
string pavoFolder = Path.Combine(System.Configuration.ConfigurationManager.AppSettings["pavoPath"], p.Codigo);
if (!Directory.Exists(pavoFolder)) Directory.CreateDirectory(pavoFolder);
//Creamos el acceso directo a la carpeta de PAVO
if (p.productos.IdModulo == (int)EnumsHelper.Modulos.Obras)
{
string pavoShortCutName = "002_" + p.Codigo + "_PVOD.lnk";
string pavoShortCutPath = Path.Combine(servicePaht, pavoShortCutName);
if (!File.Exists(pavoShortCutPath)) CreateShortCut(pavoShortCutPath, pavoFolder);
}
//Copiamos las plantilla de la estructura de carpetas del servicio
if (Directory.Exists(directoryTemplate) && p.IdEstado == (int)EnumsHelper.EstadoPresupuesto.Aprobado)
{
foreach (string dirName in Directory.GetDirectories(directoryTemplate))
{
if (dirName.Trim().ToLower().Contains(p.productos.Nombre.Trim().ToLower()))
{
string originalPath = Path.Combine(directoryTemplate, dirName);
CopyDirectory(originalPath, servicePaht, p.Codigo);
break;
}
}
}
}
}
catch (Exception ex)
{
LogHelper.Error(ex);
throw ex;
}
}
}
}
}
As a workaround, you can disable impersonation and then use the shell to create the shortcut file in a temporary directory. 解决方法是,可以禁用模拟,然后使用外壳程序在临时目录中创建快捷方式文件。 You can then pass this file as a byte array to the impersonated code, where it can be saved to the right path.
然后,您可以将此文件作为字节数组传递给模拟的代码,在此处可以将其保存到正确的路径。
public void CreateShortCut(string shorcutPath, string shortcutTarget)
{
byte[] bytes = null;
// Disable impersonation
using (System.Security.Principal.WindowsImpersonationContext ctx = System.Security.Principal.WindowsIdentity.Impersonate(IntPtr.Zero))
{
// Get a temp file name (the shell commands won't work without .lnk extension)
var path = Path.GetTempPath();
string temp = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".lnk");
try
{
WshShell shell = new WshShell();
IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(temp);
shortcut.TargetPath = shortcutTarget;
shortcut.Save();
bytes = System.IO.File.ReadAllBytes(temp);
}
finally
{
if (System.IO.File.Exists(temp)) System.IO.File.Delete(temp);
}
}
// Impersonation resumed
System.IO.File.WriteAllBytes(shorcutPath, bytes);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.