2010-04-06 163 views
3

我有一个我在VB.net中编写的实用程序,它作为计划任务运行。它在内部调用另一个可执行文件,并且必须访问映射的驱动器。显然,Windows在用户未登录时访问映射驱动器的计划任务存在问题,即使认证凭证已提供给任务本身。好的。将ProcessStartInfo.WorkingDirectory设置为UNC路径

为了解决这个问题,我刚刚通过我的应用程序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() 

这是我与映射驱动器中使用相同的实现,但是使用UNC路径,进程不表现得好像UNC路径是工作目录。

是否有任何已知问题将ProcessStartInfo.WorkingDirectory设置为UNC路径?如果不是,我做错了什么?

回答

7

用户未登录时映射驱动器的问题是它们不存在。驱动器仅映射并可用于当前登录的用户。如果没有人登录,则不映射任何驱动器。

作为一种解决方法,您可以通过CMD运行,调用PUSHD,它将您的UNC映射到幕后驱动器,然后执行您的代码。我已经从我的system32复制了tree.com文件,并将它放在我的文件服务器上,名称为“tree4.com”,并且此代码按预期工作(我也重定向标准输出,以便可以看到调用的结果,但这是不需要)

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 
0

我遇到了这个问题,接受的解决方案对我来说有点复杂。我所做的是采取UNC路径并将其内容复制到[Path.GetTempDir()]\[Guid.NewGuid().ToString()],然后将其用作我的工作目录process.StartInfo.WorkingDirectory。将此功能包装在一个名为“Environment”的类中,该类将实现IDisposable,并在处理中清理所创建的临时目录。像这样的东西(忽略设置引用):

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(); 
       } 

而且ProcessEnvironment样子:

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); 
      } 
     } 
    }