Pregunta

I tiene una utilidad que he escrito en VB.net que se ejecuta como tareas programadas. Se llama internamente otro ejecutable y tiene que tener acceso a una unidad asignada. Al parecer, Windows tiene problemas con las tareas programadas con el acceso unidades asignadas cuando el usuario no está conectado, incluso cuando se suministran las credenciales de autenticación a la tarea en sí. Ok, está bien.

Para evitar esto que acaba de pasar mi solicitud la ruta UNC.

process.StartInfo.FileName = 'name of executable'
process.StartInfo.WorkingDirectory = '\\unc path\'
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
process.StartInfo.Arguments = 'arguments to executable'
process.Start()

Esta es la misma aplicación que se utiliza con la unidad asignada, sin embargo usando la ruta UNC, el proceso no se está comportando como si la ruta UNC es el directorio de trabajo.

¿Hay algún problema conocido de ajuste ProcessStartInfo.WorkingDirectory a una ruta UNC? Si no, ¿qué estoy haciendo mal?

¿Fue útil?

Solución

Su problema con las unidades asignadas cuando los usuarios no se registran en es que no existen. Sólo las unidades se asignan y disponible para el usuario actualmente conectado. Si no hay nadie conectado, no hay unidades se asignan.

Como solución alternativa se puede ejecutar a través de CMD, PUSHD llamada que va a asignar el UNC a una unidad detrás de las escenas y luego ejecutar su código. He copiado el archivo tree.com de mi system32 y la coloqué en mi servidor de archivos como "tree4.com" y el código funciona como se espera (también estoy redirigiendo la salida estándar para que pueda ver los resultados de la llamada pero eso es no es necesario)

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Using P As New Process()
        'Launch a standard hidden command window
        P.StartInfo.FileName = "cmd.exe"
        P.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
        P.StartInfo.CreateNoWindow = True

        'Needed to redirect standard error/output/input
        P.StartInfo.UseShellExecute = False

        P.StartInfo.RedirectStandardInput = True
        P.StartInfo.RedirectStandardOutput = True

        'Add handler for when data is received
        AddHandler P.OutputDataReceived, AddressOf SDR

        'Start the process
        P.Start()

        'Begin async data reading
        P.BeginOutputReadLine()

        '"Map" our drive
        P.StandardInput.WriteLine("pushd \\file-server\File-Server")

        'Call our command, you could pass args here if you wanted
        P.StandardInput.WriteLine("tree2.com  c:\3ea7025b247d0dfb7731a50bf2632f")

        'Once our command is done CMD.EXE will still be sitting around so manually exit
        P.StandardInput.WriteLine("exit")
        P.WaitForExit()
    End Using

    Me.Close()
End Sub
Private Sub SDR(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
    Trace.WriteLine(e.Data)
End Sub

Otros consejos

me encontré con este problema y la solución aceptada es un poco complicado para mí. Lo que hice fue tomar la ruta UNC y copiar el contenido del mismo a [Path.GetTempDir()]\[Guid.NewGuid().ToString()] y luego usar eso como mi directorio de trabajo para el process.StartInfo.WorkingDirectory. Envolver esta funcionalidad en una clase denominada "Medio Ambiente", que pondrá en práctica IDisposable y en el disponer limpiar el directorio temporal que ha creado. Algo como esto (omitir las referencias configuración):

 using (var env = new ProcessEnvironment(settings))
                {
                    filePath = Path.Combine(env.WorkingDirectory, settings.ApplicationEXE);
                    var psi = new ProcessStartInfo
                    {
                        UseShellExecute = false,
                        FileName = filePath,
                        WorkingDirectory = env.WorkingDirectory,
                        Arguments = (args != null && args.Length > 0 ? String.Join(" ", args) : null)
                    };

                    var proc = Process.Start(psi);

                    if (env.ExecutingFromTempDir || settings.WaitForExit)
                        proc.WaitForExit();
                }

y se ve ProcessEnvironment como:

 class ProcessEnvironment : IDisposable
    {
        private Settings itsSettings;
        private string itsTempDestDirectory;
        public string WorkingDirectory { get; set; }
        public bool ExecutingFromTempDir { get { return !String.IsNullOrEmpty(itsTempDestDirectory); } }

        public ProcessEnvironment(Settings settings)
        {
            this.itsSettings = settings;

            WorkingDirectory = GetWorkingDirectory();
        }

        private string GetWorkingDirectory()
        {
            var dirInfo = new DirectoryInfo(itsSettings.StartupFolder);

            if (!IsUncDrive(dirInfo))
                return itsSettings.StartupFolder;

            return CreateWorkingDirectory(dirInfo);
        }

        private string CreateWorkingDirectory(DirectoryInfo dirInfo)
        {
            var srcPath = dirInfo.FullName;
            itsTempDestDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
            Directory.CreateDirectory(itsTempDestDirectory);

            //Now Create all of the directories
            foreach (string dirPath in Directory.GetDirectories(srcPath, "*", SearchOption.AllDirectories))
                Directory.CreateDirectory(dirPath.Replace(srcPath, itsTempDestDirectory));

            //Copy all the files & Replaces any files with the same name
            foreach (string newPath in Directory.GetFiles(srcPath, "*.*", SearchOption.AllDirectories))
                File.Copy(newPath, newPath.Replace(srcPath, itsTempDestDirectory), true);

            return itsTempDestDirectory;
        }

        private bool IsUncDrive(DirectoryInfo dirInfo)
        {
            Uri uri = null;
            if (!Uri.TryCreate(dirInfo.FullName, UriKind.Absolute, out uri))
            {
                return false;
            }
            return uri.IsUnc;
        }



        public void Dispose()
        {
            try
            {
                if (ExecutingFromTempDir)
                    Directory.Delete(itsTempDestDirectory, true);

            }
            catch (Exception ex)
            {  //do nothing - if we can't delete then we can't do it
                Console.WriteLine("Failed in Dispose: " + ex);
            }
        }
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top