2010-04-06 198 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); 
      } 
     } 
    }