0
我在創建服務器上的快捷方式時遇到問題。它總是拋出異常:C#:ShortCut and Impersonation
訪問被拒絕。 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(默認情況下使用的用戶)無法訪問目標目錄,並且我無法授予訪問權限。因此此行會引發異常 – Rumpelstinsk
只要存在「默認」用戶(禁用模擬時假定的身份標識)具有寫入權限的目錄,就應該可以工作。在我的片段中,這個「staging」目錄恰好是由'Path.GetTempPath()'提供的臨時目錄,因爲它用於我的IIS應用程序池的標識。 – nedmund