C #: ярлык и олицетворение

c# shortcut impersonation

253 просмотра

1 ответ

1925 Репутация автора

У меня проблема с созданием ярлыка на сервере. Это всегда выдает исключение:

Доступ не разрешен. 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;
                        }
                    }
                }
            }                       
        }
Автор: Rumpelstinsk Источник Размещён: 18.07.2016 07:25

Ответы (1)


0 плюса

510 Репутация автора

В качестве обходного пути вы можете отключить олицетворение, а затем использовать оболочку для создания файла ярлыка во временном каталоге. Затем вы можете передать этот файл в виде байтового массива в олицетворенный код, где он может быть сохранен по правильному пути.

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);
}
Автор: Ned Howley Размещён: 02.01.2017 12:36
Вопросы из категории :
32x32