서버에 바로 가기를 만드는 데 문제가 있습니다. 항상 예외가 throw됩니다.C# : ShortCut 및 가장
액세스가 거부되었습니다. 0x80070005
바로 가기 위치 또는 바로 가기 대상 때문에 문제가 발생하는지 정말 모르겠습니다.
파일 시스템에 액세스하려면 가장을 사용해야합니다. IO.File
및 IO.Directory
을 사용하여 디렉토리를 만들거나 파일을 복사 및 제거하는 등의 작업을 아무런 문제없이 수행 할 수 있습니다. 또한 파일 리포지토리에 대한 원격 데스크톱을 가장 사용자와 함께 열면 모든 문제가있는 바로 가기를 만들 수 있습니다.
그러나 바로 가기를 만들려면 WHSell을 사용하고 있으며 가장이라는 문제가있는 것으로 보입니다. 어떤 아이디어?
이 내 코드입니다 :
#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;
}
}
}
}
}
내 상황에는 적용되지 않습니다. 귀하의 코드에서'shortcut.Save()'를 사용하면 사용 된 사용자가 대상 위치에 액세스 할 수있는 권한이 다시 필요합니다. IIS_IUSER (기본적으로 사용되는 사용자)가 대상 디렉터리에 액세스 할 수 없기 때문에 가장에 대한 액세스 권한을 부여 할 수 없기 때문에 가장을 사용하지 않도록 설정할 수 없습니다. 따라서이 줄은 예외를 throw합니다. – Rumpelstinsk
"기본"사용자 (가장을 사용하지 않도록 설정된 ID)에 쓰기 권한이있는 디렉터리가 있으면이 작업이 작동합니다. 나의 발췌 문장에서이 "스테이징"디렉토리는 IIS 응용 프로그램 풀의 ID로 작동 한 이후 Path.GetTempPath()가 제공 한 임시 디렉토리가됩니다. – nedmund